package cn.ug.pay.service.impl;

import cn.ug.activity.mq.RewardsMQ;
import cn.ug.bean.base.SerializeObject;
import cn.ug.bean.type.ResultType;
import cn.ug.config.RedisGlobalLock;
import cn.ug.core.SerializeObjectError;
import cn.ug.core.ensure.Ensure;
import cn.ug.enums.*;
import cn.ug.feign.CouponRepertoryService;
import cn.ug.feign.LotteryService;
import cn.ug.feign.PriceService;
import cn.ug.feign.RateSettingsService;
import cn.ug.mall.bean.GoldBeanProvide;
import cn.ug.mq.DelayMessagePostProcessor;
import cn.ug.msg.bean.status.CommonConstants;
import cn.ug.msg.mq.Msg;
import cn.ug.msg.mq.WxMessageParamBean;
import cn.ug.msg.mq.WxNotifyData;
import cn.ug.operation.bean.LotteryBean;
import cn.ug.operation.bean.LotteryJoin;
import cn.ug.pay.bean.enumeration.TbillStatusRemark;
import cn.ug.pay.bean.enumeration.TbillTypeEnum;
import cn.ug.pay.bean.status.TbillStatusEnum;
import cn.ug.pay.bean.type.BillType;
import cn.ug.pay.bean.type.TbillSourceEnum;
import cn.ug.pay.bean.type.TradeType;
import cn.ug.pay.mapper.*;
import cn.ug.pay.mapper.entity.*;
import cn.ug.pay.service.PayGoldBeanRecordService;
import cn.ug.pay.service.PayTbillLeasebackService;
import cn.ug.pay.service.PayTbillSoldService;
import cn.ug.util.BigDecimalUtil;
import cn.ug.util.ConstantUtil;
import cn.ug.util.SerialNumberWorker;
import cn.ug.util.UF;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;

import static cn.ug.config.QueueName.*;
import static cn.ug.util.ConstantUtil.COLON;
import static cn.ug.util.ConstantUtil.NORMAL_DATE_FORMAT;
import static cn.ug.util.RedisConstantUtil.LOTTERY_DOUBLEELEVEN_DRAW_NUM_KEY;

@Service
public class PayTbillLeasebackServiceImpl implements PayTbillLeasebackService {
    private Log log = LogFactory.getLog(PayTbillLeasebackServiceImpl.class);
    @Autowired
    private PayTbillLeasebackMapper payTbillLeasebackMapper;
    @Autowired
    private RedisGlobalLock redisGlobalLock;
    @Autowired
    private PayTbillMapper payTbillMapper;
    @Autowired
    private PayTbillStatisticsMapper payTbillStatisticsMapper;
    @Autowired
    private MemberAccountMapper memberAccountMapper;
    @Autowired
    private BillMapper billMapper;
    @Autowired
    private PayTbillStatusMapper payTbillStatusMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;
    @Autowired
    private PayGoldBeanRecordMapper payGoldBeanRecordMapper;
    @Autowired
    private RateSettingsService rateSettingsService;
    @Autowired
    private PayGoldBeanRecordService payGoldBeanRecordService;
    @Autowired
    private CouponRepertoryService couponRepertoryService;
    @Autowired
    private PayTbillSoldService payTbillSoldService;
    @Autowired
    private LotteryService lotteryService;
    @Autowired
    private PriceService priceService;
    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void completeBill(String orderNO) {
        String key = "PayTbillLeasebackServiceImpl:completeBill:" + orderNO;
        if (!redisGlobalLock.lock(key)) {
            return;
        }
        try {
            PayTbillLeaseback payTbillLeaseback = payTbillLeasebackMapper.selectByOrderNO(orderNO);
            if (payTbillLeaseback == null || payTbillLeaseback.getStatus() == 1) {
                return;
            }
            if (payTbillLeaseback.getIncomeType() != 1 && payTbillLeaseback.getIncomeType() != 2) {
                return;
            }
            PayTbill payTbill = payTbillMapper.selectByOrderNO(payTbillLeaseback.getTbillNO());
            if (payTbill == null || payTbill.getStatus() != TbillStatusEnum.LEASEBACK.getStatus()) {
                return;
            }
            PayTbillStatistics payTbillStatistics = payTbillStatisticsMapper.selectByMemberId(payTbill.getMemberId());
            if (payTbillStatistics == null) {
                return;
            }
            // 1. 更改回租表信息；
            Map<String, Object> leasebackParams = new HashMap<String, Object>();
            leasebackParams.put("status", 1);
            leasebackParams.put("grantTime", UF.getFormatDateTime(UF.getDateTime()));
            leasebackParams.put("orderNO", payTbillLeaseback.getOrderNO());
            int rows = payTbillLeasebackMapper.update(leasebackParams);
            Ensure.that(rows).isLt(1, "00000005");
            // 2. 更改提单表信息；
            Map<String, Object> param = new HashMap<String, Object>();
            param.put("orderNO", payTbillLeaseback.getTbillNO());
            param.put("status", TbillStatusEnum.PAY_SUCCESS.getStatus());
            param.put("modifyTime", UF.getFormatDateTime(UF.getDateTime()));
            param.put("leasebackTimes", payTbill.getLeasebackTimes() + 1);
            param.put("source", TbillSourceEnum.LEASEBACK.getValue());
            param.put("readed", 0);
            rows = payTbillMapper.update(param);
            Ensure.that(rows).isLt(1, "00000005");
            // 3. 更改提单统计表信息；
            Map<String, Object> staParam = new HashMap<String, Object>();
            staParam.put("memberId", payTbill.getMemberId());
            staParam.put("pendingBills", payTbillStatistics.getPendingBills() + 1);
            staParam.put("pendingGram", payTbillStatistics.getPendingGram() + payTbill.getTotalGram());
            staParam.put("leasebackBills", payTbillStatistics.getLeasebackBills() - 1);
            staParam.put("leasebackGram", payTbillStatistics.getLeasebackGram() - payTbill.getTotalGram());
            staParam.put("leasebackIncomeAmount", payTbillStatistics.getLeasebackIncomeAmount().subtract(payTbillLeaseback.getIncomeAmount()));
            staParam.put("leasebackIncomeGram", payTbillStatistics.getLeasebackIncomeGram().subtract(payTbillLeaseback.getIncomeGram()));
            staParam.put("leasebackIncomeBeans", payTbillStatistics.getLeasebackIncomeBeans() - payTbillLeaseback.getIncomeBeans());
            staParam.put("incomeAmount", payTbillStatistics.getIncomeAmount().add(payTbillLeaseback.getIncomeAmount()));
            staParam.put("incomeGram", payTbillStatistics.getIncomeGram().add(payTbillLeaseback.getIncomeGram()));
            staParam.put("incomeBeans", payTbillStatistics.getIncomeBeans() + payTbillLeaseback.getIncomeBeans());
            rows = payTbillStatisticsMapper.update(staParam);
            Ensure.that(rows).isLt(1, "00000005");
            // 4. 奖励发放
            MemberAccount memberAccount = memberAccountMapper.findByMemberId(payTbill.getMemberId());
            Ensure.that(memberAccount == null).isTrue("17000421");
            if (payTbillLeaseback.getIncomeType() == 1) {
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("id", memberAccount.getId());
                map.put("fundAmount", memberAccount.getFundAmount().add(payTbillLeaseback.getIncomeAmount()));
                map.put("usableAmount", memberAccount.getUsableAmount().add(payTbillLeaseback.getIncomeAmount()));
                rows = memberAccountMapper.updateByPrimaryKeySelective(map);
                Ensure.that(rows).isLt(1, "00000005");
                // 5. 新增收支记录
                Bill billBean = new Bill();
                billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
                billBean.setMemberId(payTbill.getMemberId());
                billBean.setAmount(payTbillLeaseback.getIncomeAmount());
                billBean.setFee(BigDecimal.ZERO);
                billBean.setActualAmount(payTbillLeaseback.getIncomeAmount());
                billBean.setType(BillType.INCOME.getValue());
                billBean.setId(UF.getRandomUUID());
                billBean.setTradeType(TradeType.LEASEBACK_REWARDS.getValue());
                billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
                rows = billMapper.insert(billBean);
                Ensure.that(rows).isLt(1, "00000005");
            } else if (payTbillLeaseback.getIncomeType() == 2) {
                Map<String, Object> accountParam = new HashMap<String, Object>();
                accountParam.put("id", memberAccount.getId());
                accountParam.put("freezeBean", memberAccount.getFreezeBean() - payTbillLeaseback.getIncomeBeans());
                accountParam.put("usableBean", memberAccount.getUsableBean() + payTbillLeaseback.getIncomeBeans());
                accountParam.put("totalBean", memberAccount.getFreezeBean() + memberAccount.getUsableBean());
                rows = memberAccountMapper.updateByPrimaryKeySelective(accountParam);
                Ensure.that(rows).isLt(1, "00000005");

                PayGoldBeanRecord beanRecord = new PayGoldBeanRecord();
                beanRecord.setOrderNO(OrderNOPrefixEnum.GB.name() + SerialNumberWorker.getInstance().nextId());
                beanRecord.setType(1);
                beanRecord.setRemark(GoldBeanRemarkEnum.LEASEBACK_REWARDS.getRemark());
                beanRecord.setGoldBean(payTbillLeaseback.getIncomeBeans());
                beanRecord.setGoldGram(payTbillLeaseback.getIncomeGram());
                beanRecord.setMemberId(memberAccount.getMemberId());
                beanRecord.setAddTime(UF.getFormatDateTime(LocalDateTime.now()));
                beanRecord.setSuccessTime(UF.getFormatDateTime(LocalDateTime.now()));
                rows = payGoldBeanRecordMapper.insert(beanRecord);
                Ensure.that(rows).isLt(1, "00000005");
            }

            /**
             * 安稳金到期后自动卖出，将到期日 2 点的金价和买入时的金价做比对，取其高着卖出，卖出时自动结算其手续费
             */
            if (payTbill.getProductType() != null && ProductTypeEnum.SMOOTH_GOLD.getType() == payTbill.getProductType()) {
                log.info("安稳金到期自动出售开始......");
                String point = "02:00";
                SimpleDateFormat format = new SimpleDateFormat(NORMAL_DATE_FORMAT);
                Calendar calendar = Calendar.getInstance();
                calendar.add(Calendar.DAY_OF_YEAR, -1);
                String someday = format.format(calendar.getTime()) + " " + point;
                SerializeObject<Double> result = priceService.getSomedayPrice(someday);
                BigDecimal currentGoldPrice = BigDecimal.ZERO;
                if (payTbill.getGoldPrice().compareTo(new BigDecimal(result.getData().toString())) >= 0) {
                    currentGoldPrice = payTbill.getGoldPrice();
                } else {
                    currentGoldPrice = new BigDecimal(result.getData().toString());
                }
                String saleNO = payTbillSoldService.saleJob(payTbillLeaseback.getTbillNO(), currentGoldPrice);
                if (StringUtils.isBlank(saleNO)) {
                    Ensure.that(0).isLt(1, "00000005");
                }
                log.info("安稳金到期自动出售结束......");
            }
            // 6. 消息通知
            Msg msg = new Msg();
            msg.setMemberId(payTbill.getMemberId());
            msg.setType(CommonConstants.MsgType.BUY_GOLD_EXPIRE.getIndex());
            Map<String, String> paramMap = new HashMap<>();
            paramMap.put("productName", payTbill.getProductName());
            paramMap.put("addGram", String.valueOf(payTbill.getTotalGram()));
            paramMap.put("gram", String.valueOf(payTbillStatistics.getPendingGram() + payTbill.getTotalGram()));
            msg.setParamMap(paramMap);
            amqpTemplate.convertAndSend(QUEUE_DELAY_PER_MESSAGE_TTL_MSG_SEND, msg, new DelayMessagePostProcessor(8 * 60 * 60 * 1000));
            //amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);

            SimpleDateFormat format = new SimpleDateFormat(ConstantUtil.NORMAL_TIME_FORMAT);
            String monthAndDay = "";
            try {
                Calendar endCalendar = Calendar.getInstance();
                endCalendar.setTime(format.parse(payTbillLeaseback.getActualTime()));
                monthAndDay = (endCalendar.get(Calendar.MONTH) + 1) + "月" + endCalendar.get(Calendar.DAY_OF_MONTH) + "日";
            } catch (ParseException e) {
                e.printStackTrace();
            }

            WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
            wxMessageParamBean.setMemberId(payTbill.getMemberId());
            WxNotifyData wxNotifyData = new WxNotifyData();
            Map<String, WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
            WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
            wxMessageParamBean.setType(WxTemplateEnum.LEASEBACK_BECOME_DUE.getType());
            WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.LEASEBACK_BECOME_DUE.getType());

            first.setDataValue(wxTemplateEnum.getFirstData().replace("{orderNO}", payTbill.getOrderNO()).replace("{monthAndDay}", monthAndDay));
            wxParamMap.put("first", first);

            WxNotifyData.TemplateDataAttr orderNOInfo = new WxNotifyData.TemplateDataAttr();
            orderNOInfo.setDataValue(payTbill.getOrderNO());
            wxParamMap.put("OrderSn", orderNOInfo);

            WxNotifyData.TemplateDataAttr status = new WxNotifyData.TemplateDataAttr();
            status.setDataValue(TbillStatusEnum.PAY_SUCCESS.getRemark());
            wxParamMap.put("OrderStatus", status);

            WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
            remark.setDataValue(wxTemplateEnum.getRemark());
            wxParamMap.put("remark", remark);

            wxNotifyData.setData(wxParamMap);
            wxMessageParamBean.setTemplateData(wxNotifyData);
            //amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
            amqpTemplate.convertAndSend(QUEUE_DELAY_PER_MESSAGE_TTL_MSG_WX_SEND, wxMessageParamBean, new DelayMessagePostProcessor(8 * 60 * 60 * 1000));
        } finally {
            redisGlobalLock.unlock(key);
        }
    }

    @Override
    public int countSuccessfulNum(String memberId) {
        if (StringUtils.isNotBlank(memberId)) {
            return payTbillLeasebackMapper.countSuccessfulNum(memberId);
        }
        return 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean save(PayTbillLeaseback payTbillLeaseback) {
        if (payTbillLeaseback != null) {
            String key = "PayTbillLeasebackServiceImpl:save:" + payTbillLeaseback.getTbillNO();
            if (!redisGlobalLock.lock(key)) {
                return false;
            }
            try {
                PayTbill payTbill = payTbillMapper.selectByOrderNO(payTbillLeaseback.getTbillNO());
                if (payTbill == null) {
                    return false;
                }
                if (payTbill.getStatus() != TbillStatusEnum.PAY_SUCCESS.getStatus()) {
                    return false;
                }
                Map<String, Object> searchParams = new HashMap<String, Object>();
                searchParams.put("tbillNO", payTbillLeaseback.getTbillNO());
                searchParams.put("status", 1);
                int num = payTbillLeasebackMapper.count(searchParams);
                int successfulNum = payTbillLeasebackMapper.countSuccessfulNum(payTbill.getMemberId());
                int rows = payTbillLeasebackMapper.insert(payTbillLeaseback);
                Ensure.that(rows).isLt(1, "00000005");
                if (StringUtils.isNotBlank(payTbillLeaseback.getCouponId())) {
                    BigDecimal discountAmount = BigDecimalUtil.to2Point(new BigDecimal(payTbillLeaseback.getCouponAmount()).divide(new BigDecimal(1000)).multiply(payTbillLeaseback.getGoldPrice()));
                    log.info("***************couponId{}"+payTbillLeaseback.getCouponId());
                    log.info("***************discountAmount{}"+discountAmount);
                    log.info("***************orderNO{}"+payTbillLeaseback.getOrderNO());
                    SerializeObject usedResult = couponRepertoryService.consumeCoupon(payTbillLeaseback.getCouponId(), discountAmount, payTbillLeaseback.getOrderNO());
                    String useCoupo = JSONObject.toJSONString(usedResult);
                    log.info("***************回租优惠劵使用结果{}"+useCoupo);
                  /*  if (usedResult == null || usedResult.getCode() != ResultType.NORMAL) {
                        Ensure.that(0).isLt(1, "00000005");
                    }*/
                }
                if (successfulNum == 0) {
                    SerializeObject rateBean = rateSettingsService.get(RateKeyEnum.GOLD_BEAN_PROVIDE.getKey());
                    if (rateBean != null && rateBean.getData() != null) {
                        GoldBeanProvide goldBeanProvide = JSON.parseObject(JSONObject.toJSONString(rateBean.getData()), GoldBeanProvide.class);
                        if (goldBeanProvide != null && goldBeanProvide.getFirstLeaseBack() != null && goldBeanProvide.getFirstLeaseBack() > 0) {
                            int goldBeans = goldBeanProvide.getFirstLeaseBack();
                            String remark = GoldBeanRemarkEnum.LEASEBACK_SUCCESS_REWARDS.getRemark();
                            int type = 1;
                            PayGoldBeanRecord beanRecord = new PayGoldBeanRecord();
                            beanRecord.setOrderNO(OrderNOPrefixEnum.GB.name() + SerialNumberWorker.getInstance().nextId());
                            beanRecord.setType(type);
                            beanRecord.setRemark(remark);
                            beanRecord.setGoldBean(goldBeans);
                            beanRecord.setGoldGram(new BigDecimal(goldBeans / 10000.0));
                            beanRecord.setMemberId(payTbill.getMemberId());
                            beanRecord.setAddTime(UF.getFormatDateTime(LocalDateTime.now()));
                            beanRecord.setSuccessTime(UF.getFormatDateTime(LocalDateTime.now()));
                            boolean result = payGoldBeanRecordService.save(beanRecord);
                            if (!result) {
                                Ensure.that(0).isLt(1, "00000005");
                            }
                        }
                    }
                }
                MemberAccount memberAccount = memberAccountMapper.findByMemberId(payTbill.getMemberId());
                if (memberAccount == null) {
                    Ensure.that(0).isLt(1, "00000005");
                }
                //回租优惠模板-金豆发放
                if (payTbillLeaseback.getDiscountAmountType() == 3 && payTbillLeaseback.getDiscountAmount().intValue() > 0) {
                    PayGoldBeanRecord beanRecord = new PayGoldBeanRecord();
                    beanRecord.setOrderNO(OrderNOPrefixEnum.GB.name() + SerialNumberWorker.getInstance().nextId());
                    beanRecord.setType(1);
                    beanRecord.setRemark(GoldBeanRemarkEnum.LEASEBACK_ENJOY_REWARDS.getRemark());
                    beanRecord.setGoldBean(payTbillLeaseback.getDiscountAmount().intValue());
                    beanRecord.setGoldGram(new BigDecimal(payTbillLeaseback.getDiscountAmount().intValue() / 10000.0));
                    beanRecord.setMemberId(payTbill.getMemberId());
                    beanRecord.setAddTime(UF.getFormatDateTime(LocalDateTime.now()));
                    beanRecord.setSuccessTime(UF.getFormatDateTime(LocalDateTime.now()));
                    boolean result = payGoldBeanRecordService.save(beanRecord);
                    Ensure.that(rows).isLt(1, "00000005");
                }
                //回租优惠模板-现金发放
                if (payTbillLeaseback.getDiscountAmountType() == 1 && payTbillLeaseback.getDiscountAmount().doubleValue() > 0) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("id", memberAccount.getId());
                    map.put("fundAmount", memberAccount.getFundAmount().add(payTbillLeaseback.getDiscountAmount()));
                    map.put("usableAmount", memberAccount.getUsableAmount().add(payTbillLeaseback.getDiscountAmount()));
                    rows = memberAccountMapper.updateByPrimaryKeySelective(map);
                    Ensure.that(rows).isLt(1, "00000005");
                    Bill billBean = new Bill();
                    billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
                    billBean.setMemberId(payTbill.getMemberId());
                    billBean.setAmount(payTbillLeaseback.getDiscountAmount());
                    billBean.setFee(BigDecimal.ZERO);
                    billBean.setActualAmount(payTbillLeaseback.getDiscountAmount());
                    billBean.setType(BillType.INCOME.getValue());
                    billBean.setId(UF.getRandomUUID());
                    billBean.setTradeType(TradeType.LEASEBACK_ENJOY_REWARDS.getValue());
                    billBean.setOrderId(SerialNumberWorker.getInstance().nextId());
                    rows = billMapper.insert(billBean);
                    Ensure.that(rows).isLt(1, "00000005");
                }


                if (payTbillLeaseback.getIncomeType() == 2) {
                    Map<String, Object> accountParam = new HashMap<String, Object>();
                    accountParam.put("id", memberAccount.getId());
                    accountParam.put("freezeBean", memberAccount.getFreezeBean() + payTbillLeaseback.getIncomeBeans());
                    accountParam.put("totalBean", memberAccount.getFreezeBean() + payTbillLeaseback.getIncomeBeans() + memberAccount.getUsableBean());
                    rows = memberAccountMapper.updateByPrimaryKeySelective(accountParam);
                    Ensure.that(rows).isLt(1, "00000005");
                }

                Map<String, Object> param = new HashMap<String, Object>();
                param.put("orderNO", payTbillLeaseback.getTbillNO());
                param.put("status", TbillStatusEnum.LEASEBACK.getStatus());
                param.put("modifyTime", UF.getFormatDateTime(UF.getDateTime()));
                param.put("readed", 0);
                rows = payTbillMapper.update(param);
                Ensure.that(rows).isLt(1, "00000005");
                PayTbillStatistics payTbillStatistics = payTbillStatisticsMapper.selectByMemberId(payTbill.getMemberId());
                if (payTbillStatistics == null) {
                    rows = 0;
                    Ensure.that(rows).isLt(1, "00000005");
                } else {
                    Map<String, Object> staParam = new HashMap<String, Object>();
                    staParam.put("memberId", payTbill.getMemberId());
                    staParam.put("pendingBills", payTbillStatistics.getPendingBills() - 1);
                    staParam.put("pendingGram", payTbillStatistics.getPendingGram() - payTbill.getTotalGram());
                    staParam.put("leasebackBills", payTbillStatistics.getLeasebackBills() + 1);
                    staParam.put("leasebackGram", payTbillStatistics.getLeasebackGram() + payTbill.getTotalGram());
                    staParam.put("leasebackIncomeAmount", payTbillStatistics.getLeasebackIncomeAmount().add(payTbillLeaseback.getIncomeAmount()));
                    staParam.put("leasebackIncomeGram", payTbillStatistics.getLeasebackIncomeGram().add(payTbillLeaseback.getIncomeGram()));
                    staParam.put("leasebackIncomeBeans", payTbillStatistics.getLeasebackIncomeBeans() + payTbillLeaseback.getIncomeBeans());
                    rows = payTbillStatisticsMapper.update(staParam);
                    Ensure.that(rows).isLt(1, "00000005");
                }
                PayTbillStatus payTbillStatus = new PayTbillStatus();
                payTbillStatus.setTbillNO(payTbillLeaseback.getTbillNO());
                payTbillStatus.setOrderNO(SerialNumberWorker.getInstance().nextId());
                payTbillStatus.setAddTime(UF.getFormatDateTime(UF.getDateTime()));
                payTbillStatus.setType(TbillTypeEnum.LEASEBACK.getValue());
                payTbillStatus.setStatus(TbillStatusEnum.LEASEBACK.getStatus());
                if (num > 0) {
                    payTbillStatus.setRemark(TbillStatusRemark.LEASEBACK.getValue());
                } else {
                    payTbillStatus.setRemark("");
                }
                payTbillStatus.setModifyTime(UF.getFormatDateTime(UF.getDateTime()));
                payTbillStatusMapper.insert(payTbillStatus);

                RewardsMQ rewardsMQ = new RewardsMQ();
                rewardsMQ.setProductId(payTbill.getProductId());
                rewardsMQ.setScene(4);
                rewardsMQ.setMemberId(payTbill.getMemberId());
                rewardsMQ.setOrderId(payTbillLeaseback.getOrderNO());
                rewardsMQ.setLeasebackDays(payTbillLeaseback.getLeasebackDays());
                rewardsMQ.setPayTotalAmount(payTbill.getPayAmount());
                rewardsMQ.setAmount(new BigDecimal(payTbill.getTotalGram()));
                amqpTemplate.convertAndSend(QUEUE_ACTIVITY_REWARDS, rewardsMQ);

                Msg msg = new Msg();
                msg.setMemberId(payTbill.getMemberId());
                msg.setType(CommonConstants.MsgType.LEASEBACK_WITHOUT_COUPON.getIndex());
                Map<String, String> paramMap = new HashMap<>();
                SimpleDateFormat format = new SimpleDateFormat(ConstantUtil.NORMAL_TIME_FORMAT);
                paramMap.put("productName", payTbill.getProductName());
                String monthAndDay = "";
                try {
                    Calendar startCalendar = Calendar.getInstance();
                    startCalendar.setTime(format.parse(payTbillLeaseback.getStartTime()));
                    monthAndDay = (startCalendar.get(Calendar.MONTH) + 1) + "月" + startCalendar.get(Calendar.DAY_OF_MONTH) + "日";
                    paramMap.put("monthAndDay", monthAndDay);
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                paramMap.put("leasebackDays", String.valueOf(payTbillLeaseback.getLeasebackDays()));
                String endMonthAndDay = "";
                try {
                    Calendar endCalendar = Calendar.getInstance();
                    endCalendar.setTime(format.parse(payTbillLeaseback.getActualTime()));
                    endMonthAndDay = (endCalendar.get(Calendar.MONTH) + 1) + "月" + endCalendar.get(Calendar.DAY_OF_MONTH) + "日";
                    paramMap.put("endMonthAndDay", (endCalendar.get(Calendar.MONTH) + 1) + "月" + endCalendar.get(Calendar.DAY_OF_MONTH) + "日");
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                msg.setParamMap(paramMap);

                amqpTemplate.convertAndSend(QUEUE_MSG_SEND, msg);

                WxMessageParamBean wxMessageParamBean = new WxMessageParamBean();
                wxMessageParamBean.setMemberId(payTbill.getMemberId());
                WxNotifyData wxNotifyData = new WxNotifyData();
                Map<String, WxNotifyData.TemplateDataAttr> wxParamMap = new HashMap();
                WxNotifyData.TemplateDataAttr first = new WxNotifyData.TemplateDataAttr();
                wxMessageParamBean.setType(WxTemplateEnum.LEASEBACK.getType());
                WxTemplateEnum wxTemplateEnum = WxTemplateEnum.getWxTemplateByCode(WxTemplateEnum.LEASEBACK.getType());

                first.setDataValue(wxTemplateEnum.getFirstData().replace("{orderNO}", payTbill.getOrderNO()).
                        replace("{monthAndDay}", monthAndDay).replace("{leasebackDays}", String.valueOf(payTbillLeaseback.getLeasebackDays())).
                        replace("{endMonthAndDay}", endMonthAndDay).replace("{couponInfo}", ""));
                wxParamMap.put("first", first);

                WxNotifyData.TemplateDataAttr orderNO = new WxNotifyData.TemplateDataAttr();
                orderNO.setDataValue(payTbill.getOrderNO());
                wxParamMap.put("OrderSn", orderNO);

                WxNotifyData.TemplateDataAttr status = new WxNotifyData.TemplateDataAttr();
                status.setDataValue(TbillStatusEnum.LEASEBACK.getRemark());
                wxParamMap.put("OrderStatus", status);

                WxNotifyData.TemplateDataAttr remark = new WxNotifyData.TemplateDataAttr();
                remark.setDataValue(wxTemplateEnum.getRemark());
                wxParamMap.put("remark", remark);

                wxNotifyData.setData(wxParamMap);
                wxMessageParamBean.setTemplateData(wxNotifyData);
                amqpTemplate.convertAndSend(QUEUE_MSG_WX_SEND, wxMessageParamBean);
                //双十一活动，回租增加抽奖次数
                SerializeObject<LotteryJoin> joinLottery = lotteryService.findJoinLotteryByMember(payTbill.getMemberId());
                if (joinLottery != null && joinLottery.getData() != null) {
                    log.info("*******双十一活动-回租增加抽奖次数开始*****");
                    LotteryJoin lotteryJoin = joinLottery.getData();
                    SerializeObject lotteryData = lotteryService.findLottery(lotteryJoin.getLotteryId());
                    if (lotteryData != null && lotteryData.getData() != null) {
                        LotteryBean lottery = (LotteryBean)lotteryData.getData();
                        log.info("****************双十一抽奖活动【"+lottery.getId()+"】");
                        Boolean flag = false;
                        //活动进行中
                        if (lottery == null || lottery.getId() == 0 || StringUtils.isBlank(lottery.getStartTime()) || StringUtils.isBlank(lottery.getEndTime())) {
                            flag = false;
                        } else if ((lottery.getStatus() == 2) || (UF.getDateTime().compareTo(UF.getDateTime(lottery.getStartTime())) >= 0
                                && UF.getDateTime().compareTo(UF.getDateTime(lottery.getEndTime())) <= -1)) {
                            flag = true;
                        }
                        //未达到奖励次数上限
                        int alreadyNum = 0;
                        SerializeObject intObject = lotteryService.countLotteryNumToday(payTbill.getMemberId(),lottery.getId());
                        if (intObject != null && intObject.getData() != null) {
                            alreadyNum = (Integer) intObject.getData();
                        }
                        if (alreadyNum >= lottery.getEverydayNum() + lottery.getEverydayMaxNum()) {
                            flag = false;
                        }

                        SimpleDateFormat dateFormat = new SimpleDateFormat(NORMAL_DATE_FORMAT);
                        String lottery_key = LOTTERY_DOUBLEELEVEN_DRAW_NUM_KEY + dateFormat.format(Calendar.getInstance().getTime()) + COLON + payTbill.getMemberId()+COLON+lottery.getId();
                        String value = redisTemplate.opsForValue().get(lottery_key);
                        int gotNum = 0;
                        if (StringUtils.isNotBlank(value)) {
                            gotNum = Integer.parseInt(value);
                            if (gotNum >= lottery.getEverydayMaxNum()) {
                                flag = false;
                            }
                        }

                        //增加抽奖次数
                        if (flag) {
                            lotteryService.addLotteryTimes(payTbill.getMemberId(), lottery.getId());
                            redisTemplate.opsForValue().set(lottery_key, String.valueOf(gotNum+1));
                            log.info("双十一活动,用户【"+payTbill.getMemberId()+"】成功回租，获得1次抽奖次数");
                        }

                    }
                    log.info("*******双十一活动-回租增加抽奖次数结束*****");
                }

                return true;
            } finally {
                redisGlobalLock.unlock(key);
            }
        }
        return false;
    }

    @Override
    public PayTbillLeaseback selectByOrderNO(String orderNO) {
        if (StringUtils.isNotBlank(orderNO)) {
            return payTbillLeasebackMapper.selectByOrderNO(orderNO);
        }
        return null;
    }

    @Override
    public PayTbillLeaseback selectLatestByTbillNO(String tbillNO) {
        if (StringUtils.isNotBlank(tbillNO)) {
            return payTbillLeasebackMapper.selectLatestByTbillNO(tbillNO);
        }
        return null;
    }


    @Override
    public List<PayTbillLeaseback> query(String mobile, String name, int startGram, int endGram, String startOfStartDate, String endOfStartDate, String startOfEndDate,
                                         String endOfEndDate, int status, String tbillNO, Integer[] leasebackDays, String order, String sort, int offset, int size, Integer[] productType
            , String tbillMoneyMin, String tbillMoneyMax) {
        List<String> orders = Arrays.asList("total_gram", "start_time", "end_time", "grant_time", "leaseback_times", "actual_time", "income_amount", "leaseback_days", "year_income");
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(mobile)) {
            params.put("mobile", mobile);
        }
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (startGram >= 0) {
            params.put("startGram", startGram);
        }
        if (endGram >= 0) {
            params.put("endGram", endGram);
        }
        if (StringUtils.isNotBlank(startOfStartDate)) {
            params.put("startOfStartDate", startOfStartDate);
        }
        if (StringUtils.isNotBlank(endOfStartDate)) {
            params.put("endOfStartDate", endOfStartDate);
        }
        if (StringUtils.isNotBlank(startOfEndDate)) {
            params.put("startOfEndDate", startOfEndDate);
        }
        if (StringUtils.isNotBlank(endOfEndDate)) {
            params.put("endOfEndDate", endOfEndDate);
        }
        params.put("status", status);
        if (StringUtils.isNotBlank(tbillNO)) {
            params.put("tbillNO", tbillNO);
        }
        if (orders.contains(order)) {
            params.put("order", order);
            params.put("sort", "desc");
            if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                params.put("sort", sort);
            }
        }

        if (productType != null && productType.length > 0) {
            params.put("productType", productType);
        }

        if (leasebackDays != null && leasebackDays.length > 0) {
            params.put("leasebackDays", leasebackDays);
        }

        if (StringUtils.isNotBlank(tbillMoneyMin)) {
            params.put("tbillMoneyMin", tbillMoneyMin);
        }

        if (StringUtils.isNotBlank(tbillMoneyMax)) {
            params.put("tbillMoneyMax", tbillMoneyMax);
        }
        params.put("offset", offset);
        params.put("size", size);
        return payTbillLeasebackMapper.query(params);
    }

    @Override
    public int count(String mobile, String name, int startGram, int endGram, String startOfStartDate, String endOfStartDate, String startOfEndDate, String endOfEndDate,
                     int status, String tbillNO, Integer[] leasebackDays, Integer[] productType
            , String tbillMoneyMin, String tbillMoneyMax) {
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(mobile)) {
            params.put("mobile", mobile);
        }
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (startGram >= 0) {
            params.put("startGram", startGram);
        }
        if (endGram >= 0) {
            params.put("endGram", endGram);
        }
        if (StringUtils.isNotBlank(startOfStartDate)) {
            params.put("startOfStartDate", startOfStartDate);
        }
        if (StringUtils.isNotBlank(endOfStartDate)) {
            params.put("endOfStartDate", endOfStartDate);
        }
        if (StringUtils.isNotBlank(startOfEndDate)) {
            params.put("startOfEndDate", startOfEndDate);
        }
        if (StringUtils.isNotBlank(endOfEndDate)) {
            params.put("endOfEndDate", endOfEndDate);
        }
        params.put("status", status);
        if (StringUtils.isNotBlank(tbillNO)) {
            params.put("tbillNO", tbillNO);
        }

        if (productType != null && productType.length > 0) {
            params.put("productType", productType);
        }

        if (StringUtils.isNotBlank(tbillMoneyMin)) {
            params.put("tbillMoneyMin", tbillMoneyMin);
        }

        if (StringUtils.isNotBlank(tbillMoneyMax)) {
            params.put("tbillMoneyMax", tbillMoneyMax);
        }

        if (leasebackDays != null && leasebackDays.length > 0) {
            params.put("leasebackDays", leasebackDays);
        }
        return payTbillLeasebackMapper.count(params);
    }

    @Override
    public List<PayTbillAgainLeaseback> queryAgainLeaseback(String mobile, String name, String tbillNo, int startGram, int endGram, String startAmount, String endAmount,
                                                            String s_startTime, String e_startTime, String s_endTime, String e_endTime, Integer[] leasebackDays,
                                                            Integer[] productType,String order, String sort) {
        List<String> orders = Arrays.asList("totalGram", "totalAmount", "goldPrice", "startTime", "endTime");
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(mobile)) {
            params.put("mobile", mobile);
        }
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (StringUtils.isNotBlank(tbillNo)) {
            params.put("tbillNO", tbillNo);
        }
        if (startGram >= 0) {
            params.put("startGram", startGram);
        }
        if (endGram >= 0) {
            params.put("endGram", endGram);
        }
        if (StringUtils.isNotBlank(s_startTime)) {
            params.put("s_startTime", s_startTime);
        }
        if (StringUtils.isNotBlank(e_startTime)) {
            params.put("e_startTime", e_startTime);
        }
        if (leasebackDays != null && leasebackDays.length > 0) {
            params.put("leasebackDays", leasebackDays);
        }
        if (productType != null && productType.length > 0) {
            params.put("productType", productType);
        }
        if (orders.contains(order)) {
            params.put("order", order);
            params.put("sort", "desc");
            if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                params.put("sort", sort);
            }
        }

        return payTbillLeasebackMapper.queryAgainLeaseback(params);
    }

    /**
     * 提单复投记录列表（针对用户的复投）
     *
     * @param mobile
     * @param name
     * @param tbillNO
     * @param startGram
     * @param endGram
     * @param startAmount
     * @param endAmount
     * @param s_startTime
     * @param e_startTime
     * @param s_endTime
     * @param e_endTime
     * @param leasebackDays
     * @param productIds
     * @param order
     * @param sort
     * @return
     */
    @Override
    public List<PayTbillAgainLeaseback> queryUserAgainLeasebackList(String mobile, String name, String tbillNo, int startGram, int endGram,
                                                                    String startAmount, String endAmount, String s_startTime, String e_startTime,
                                                                    String s_endTime, String e_endTime, Integer[] leasebackDays,
                                                                    Integer[] productType, String order, String sort) {
        List<String> orders = Arrays.asList("totalGram", "totalAmount", "goldPrice", "startTime", "endTime");
        Map<String, Object> params = new HashMap<String, Object>();
        if (StringUtils.isNotBlank(mobile)) {
            params.put("mobile", mobile);
        }
        if (StringUtils.isNotBlank(name)) {
            params.put("name", name);
        }
        if (StringUtils.isNotBlank(tbillNo)) {
            params.put("tbillNo", tbillNo);
        }
        if (startGram >= 0) {
            params.put("startGram", startGram);
        }
        if (endGram >= 0) {
            params.put("endGram", endGram);
        }
        if (StringUtils.isNotBlank(startAmount)) {
            params.put("startAmount", startAmount);
        }
        if (StringUtils.isNotBlank(endAmount)) {
            params.put("endAmount", endAmount);
        }
        if (StringUtils.isNotBlank(s_startTime)) {
            params.put("s_startTime", s_startTime);
        }
        if (StringUtils.isNotBlank(e_startTime)) {
            params.put("e_startTime", e_startTime);
        }
        if (StringUtils.isNotBlank(s_endTime)) {
            params.put("s_endTime", s_endTime);
        }
        if (StringUtils.isNotBlank(e_endTime)) {
            params.put("e_endTime", e_endTime);
        }
        if (leasebackDays != null && leasebackDays.length > 0) {
            params.put("leasebackDays", leasebackDays);
        }
        if (productType != null && productType.length > 0) {
            params.put("productType", productType);
        }
        if (orders.contains(order)) {
            params.put("order", order);
            params.put("sort", "desc");
            if (StringUtils.equalsIgnoreCase(sort, "asc") || StringUtils.equalsIgnoreCase(sort, "desc")) {
                params.put("sort", sort);
            }
        }

        return payTbillLeasebackMapper.queryUserAgainLeasebackList(params);
    }

    /**
     * 平台累计回租总克重
     *
     * @return
     */
    @Override
    public int findPlatformLeasebackTotalGram() {
        return payTbillLeasebackMapper.findPlatformLeasebackTotalGram();
    }
}
